#include "key.h"
#include "stdio.h"
#include "LPC17xx.h"
#include "lpc17xx_pinsel.h"
#include "lpc17xx_gpio.h"
#include "timer.h"
#include "app.h"
#include "GUI.h"
#include "GUI_LCD.h"
#include "utils.h"

#include "pttController.h"

#include "tones.h"
//#include "systen_delay.h"

#include "usart.h"

static uint16_t timeCnt = 0;
static uint8_t pressCnt = 3;   //长按计数
bool keyState = false;  //false 松开， true 按下
static uint8_t currentKey = 0;
	
void LcdKeyInit()
{
	/*********************面板按键******************************/
	PINSEL_CFG_Type PinCfg;
	/**pin config
	 *	p1.10、p1.14、p1.15、p1.16、p1.17
	 */
	PinCfg.Pinmode = PINSEL_PINMODE_PULLUP;
	
	PinCfg.OpenDrain = PINSEL_PINMODE_NORMAL;
	
	PinCfg.Pinnum = 10;
	PINSEL_ConfigPin(&PinCfg);
	PinCfg.Pinnum = 14;
	PINSEL_ConfigPin(&PinCfg);
	PinCfg.Pinnum = 15;
	PINSEL_ConfigPin(&PinCfg);
	PinCfg.Pinnum = 16;
	PINSEL_ConfigPin(&PinCfg);
	PinCfg.Pinnum = 17;
	PINSEL_ConfigPin(&PinCfg);
}

// 按键行扫描
// @param line ：1~5
//
//
uint32_t LcdKeyLineScan(uint8_t line)
{
	uint32_t Key_IO = 0;
	uint8_t temp = 0;
	switch(line){
		case 1:
			GPIO_SetDir(LCD_KEY_PORT_NUM,(1<<14)|(1<<15)|(1<<16)|(1<<17),0);	//p1.14、p1.15、p1.16、p1.17 设置为输入
			OSTimeDly(1);
			GPIO_SetDir(LCD_KEY_PORT_NUM,(1<<10),1);	//p1.10	设置为输出
			GPIO_ClearValue(LCD_KEY_PORT_NUM,(1<<10));
		
			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>14)&0x01;
			Key_IO |= (temp==0?1:0);	//B1

			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>15)&0x01;
			Key_IO |= (temp==0?1:0)<<1;	//B2

			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>16)&0x01;
			Key_IO |= (temp==0?1:0)<<2;	//B3

			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>17)&0x01;
			Key_IO |= (temp==0?1:0)<<3;	//B4
			break;
		
		case 2:
			GPIO_SetDir(LCD_KEY_PORT_NUM,(1<<10)|(1<<15)|(1<<16)|(1<<17),0);//p1.10、p1.15、p1.16、p1.17 设置为输入
			OSTimeDly(1);
			GPIO_SetDir(LCD_KEY_PORT_NUM,(1<<14),1);	//p1.14	设置为输出
			GPIO_ClearValue(LCD_KEY_PORT_NUM,(1<<14));
		
			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>10)&0x01;
			Key_IO |= (temp==0?1:0)<<4;	//B5
	
			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>15)&0x01;
			Key_IO |= (temp==0?1:0)<<5;	//B6
			
			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>16)&0x01;
			Key_IO |= (temp==0?1:0)<<6;	//B7
			
			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>17)&0x01;
			Key_IO |= (temp==0?1:0)<<7;	//B8
			break;
		
		case 3:
			GPIO_SetDir(LCD_KEY_PORT_NUM,(1<<10)|(1<<14)|(1<<16)|(1<<17),0);//p1.10、p1.14、p1.16、p1.17 设置为输入
			OSTimeDly(1);
			GPIO_SetDir(LCD_KEY_PORT_NUM,(1<<15),1);	//p1.15	设置为输出
			GPIO_ClearValue(LCD_KEY_PORT_NUM,(1<<15));
		
			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>10)&0x01;
			Key_IO |= (temp==0?1:0)<<8;	//B9
			
			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>14)&0x01;
			Key_IO |= (temp==0?1:0)<<9;	//B10
			
			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>16)&0x01;
			Key_IO |= (temp==0?1:0)<<10;	//B11
			
			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>17)&0x01;
			Key_IO |= (temp==0?1:0)<<11;	//B12
			break;
		
		case 4:
			GPIO_SetDir(LCD_KEY_PORT_NUM,(1<<10)|(1<<14)|(1<<15)|(1<<17),0);//p1.10、p1.14、p1.15、p1.17 设置为输入	
			OSTimeDly(1);
			GPIO_SetDir(LCD_KEY_PORT_NUM,(1<<16),1);	//p1.16	设置为输出
			GPIO_ClearValue(LCD_KEY_PORT_NUM,(1<<16));
		
			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>10)&0x01;
			Key_IO |= (temp==0?1:0)<<12;	//B13
			
			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>14)&0x01;
			Key_IO |= (temp==0?1:0)<<13;	//B14
			
			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>15)&0x01;
			Key_IO |= (temp==0?1:0)<<14;	//B15
			
			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>17)&0x01;
			Key_IO |= (temp==0?1:0)<<15;	//B16
			break;
		
		case 5:
			GPIO_SetDir(LCD_KEY_PORT_NUM,(1<<10)|(1<<14)|(1<<15)|(1<<16),0);//p1.10、p1.14、p1.15、p1.16 设置为输入
			OSTimeDly(1);
			GPIO_SetDir(LCD_KEY_PORT_NUM,(1<<17),1);	//p1.17	设置为输出
			GPIO_ClearValue(LCD_KEY_PORT_NUM,(1<<17));
		
			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>10)&0x01;
			Key_IO |= (temp==0?1:0)<<16;	//B17

			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>14)&0x01;
			Key_IO |= (temp==0?1:0)<<17;	//B18

			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>15)&0x01;
			Key_IO |= (temp==0?1:0)<<18;	//B19

			temp = (GPIO_ReadValue(LCD_KEY_PORT_NUM)>>16)&0x01;
			Key_IO |= (temp==0?1:0)<<19;	//B20
			break;
	}
    return Key_IO;
}



//面板按键扫描
uint32_t GetLcdKeyValue(void)
{
	uint32_t Key_L = 0;
	for(int i=1;i<=5;i++)
		Key_L |= LcdKeyLineScan(i);
	
	return Key_L;
}





void KeyInit(void)
{
	LcdKeyInit();
}


bool PPTState()
{
	uint8_t temp;
	temp = (GPIO_ReadValue(2)>>4)&0x01;

	return temp==0?1:0;
}




/** @brief 	手咪键值发送
  * 
  * @param  	data  按键数据
  * @return 
  * @note
  */
void HandKeySend(uint8_t* data)
{
	uint16_t temp=0;
	
	temp = (data[2]<<8)| data[3];
	/**< CRC校验位判断     */
	if(temp==crc16(data,2)){
		
		/**< 按下     */
		if(data[0]==1){
			//GUI_StoreKeyMsg(data[1],KEY_DOWN);
      KeySend(data[1],KEY_DOWN);
//			printf("keydown:%d\n",data[1]);
		}
		/**< 松开     */
		else{
//          //背光处理
//          if(GUI_KEY_BKLINGHT == data[1]){
//              GUI_LCDLightLoop();
//              AudioPlayCnt(AUDIO_TYPE_KEY_NORMAL,AUDIO_PLAY_TIMES_KEY_NORMAL);
//          }
          KeySend(data[1],KEY_UP);
            
//			printf("keyup:%d\n",data[1]);
		}
	}
}

// 按键扫描
void KeyScan(void *p_arg)
{
	uint8_t err;
	
	uint8_t filterCnt  = 0;
	uint8_t curStatus  = KEY_STAT_noKeyPress;
	uint32_t curKeyVal  = NO_KEY_PRESS;
	uint32_t backupVal  = NO_KEY_PRESS;
	
	uint32_t specCnt  = 0;
  
	uint32_t keyValue = 0;
	
	uint8_t pptCnt = 0;
	uint8_t pptCurState = KEY_STAT_noKeyPress;
	while(1){
        static uint16_t TaskRunningCnt  = 0;
        
		//ppt 扫描------------------------
        if(keyState==false || currentKey==GUI_KEY_PTTDOWN){
            //printf("ppt scan");
            if(PPTState()){
                /**< 非按下情况     */
                if(pptCurState!=KEY_STAT_clicking){
                    pptCnt++;
                    //按下
                    if(pptCnt==3){
                        pptCurState = KEY_STAT_clicking;
                        KeySend(GUI_KEY_PTTDOWN,KEY_DOWN);
        //					printf("ppt enter\n");
        //					pttPushOrRelease(PttPush);
                        if(!handlePttPush())
                        {
                            GUI_StoreKeyMsg(GUI_KEY_PTTDOWN, KEY_DOWN);
                        }
                    }
                }
            }
            else{
                //松手
                if(pptCurState == KEY_STAT_clicking){
                    pptCurState = KEY_STAT_noKeyPress;
                    KeySend(GUI_KEY_PTTDOWN,KEY_UP);
                    handlePttRelease();
                }
                pptCnt = 0;
            }
        }
        
		
		//面板按键扫描------------------------------
			switch(curStatus){
			case KEY_STAT_noKeyPress:
				curKeyVal = GetLcdKeyValue();
				if(curKeyVal != NO_KEY_PRESS){
					backupVal = curKeyVal;
					curStatus = KEY_STAT_filter; 
					//printf("key state filter\n");
				}
				else{
				}
				break;
				
			case KEY_STAT_filter:
				if(filterCnt>=2){
					curKeyVal = GetLcdKeyValue();
					if(curKeyVal == backupVal){
						curStatus = KEY_STAT_clicking;
						//printf("keyValue:%d\n",curKeyVal);
						switch(backupVal){
							case 0x000001:
                keyValue = GUI_KEY_1_GROUP;
								break;
							
							case 0x000002:
                keyValue = GUI_KEY_2_DIGIT;
								break;
							
							case 0x000004:
                keyValue = GUI_KEY_3_SIMULATE;
								break;
							
							case 0x000008:
                keyValue = GUI_KEY_BKLINGHT;
								break;
							
							case 0x000010:
                keyValue = GUI_KEY_4_LOG;
								break;
							
							case 0x000020:
                keyValue = GUI_KEY_5_DIRECTION;
								break;
							
							case 0x000040:
                keyValue = GUI_KEY_6_REMEMBER;
								break;
							
							case 0x000080:
                keyValue = GUI_KEY_NEW;
								break;
							
							case 0x000100:
                keyValue = GUI_KEY_7_SIGN;
								break;
							
							case 0x000200:
                keyValue = GUI_KEY_8_WEATHER;
								break;
							
							case 0x000400:
                keyValue = GUI_KEY_9_SCAN;
								break;
							
							case 0x000800:
                keyValue = GUI_KEY_ENTER;
								break;
							
							case 0x001000:
                keyValue = GUI_KEY_STAR;
								break;
							
							case 0x002000:
                keyValue = GUI_KEY_0_CALLSHIP;
								break;
							
							case 0x004000:
                keyValue = GUI_KEY_DEL;
								break;
							
							case 0x008000:
                keyValue = GUI_KEY_BACK;
								break;
							
							case 0x010000:
                keyValue = GUI_KEY_PICKUP;
								break;
							
							case 0x020000:
                keyValue = GUI_KEY_HANGUP;
								break;
							
							case 0x040000:
                keyValue = GUI_KEY_DOWN;
								break;
							
							case 0x080000:
                keyValue = GUI_KEY_UP;
								break;
							
							default:
                                curStatus = KEY_STAT_noKeyPress;
								break;
						}
            
            if(keyValue!=0){
              //GUI_StoreKeyMsg(keyValue,KEY_DOWN);
                KeySend(keyValue,KEY_DOWN);
				//printf("keyDonw:%d\n",keyValue);
            }
            
					}
					else{
						curKeyVal = NO_KEY_PRESS;
						backupVal = NO_KEY_PRESS;
						curStatus = KEY_STAT_noKeyPress;
						filterCnt = 0;
					}
				}
				else{
					filterCnt++;
				}
				break;
				
						
			case KEY_STAT_clicking:
				curKeyVal = GetLcdKeyValue();
                if(curKeyVal != backupVal){
                    if((curKeyVal&backupVal)==0){
                        curKeyVal = NO_KEY_PRESS;
                        backupVal = curKeyVal;
                        curStatus = KEY_STAT_noKeyPress;
                         KeySend(keyValue,KEY_UP);
//                        //背光键
//                        if(GUI_KEY_BKLINGHT == keyValue){
//                            GUI_LCDLightLoop();
//                            AudioPlayCnt(AUDIO_TYPE_KEY_NORMAL,AUDIO_PLAY_TIMES_KEY_NORMAL);
//                        }
                        keyValue = 0;
                    }
                }
                
				break;
				
			default:
				curKeyVal = NO_KEY_PRESS;
				backupVal = curKeyVal;
				curStatus = KEY_STAT_noKeyPress;
				break;
		}
		
        //长按判断 pressCnt: 3,4,5时，每隔500ms发一次键值，6时每隔200ms发送一次键值
        if(keyState==true){
            if(currentKey==GUI_KEY_UP||currentKey==GUI_KEY_DOWN){
                timeCnt++;
                if(pressCnt<6){
                  
                  //按下后500ms进入长按状态
                    if(pressCnt==3){
                      if(timeCnt==100){
                        timeCnt = 0;
                        GUI_StoreKeyMsg(currentKey,pressCnt);
                        pressCnt++;
                      }
                    }
                    //长按状态，200ms发送一次键值
                    else{
                      if(timeCnt==40){
                          timeCnt = 0;
                          GUI_StoreKeyMsg(currentKey,pressCnt);
                          pressCnt++;
                      }
                  }
                }
                if(pressCnt>=6){
                    if(timeCnt==20){
                      timeCnt = 0;
                        GUI_StoreKeyMsg(currentKey,pressCnt);
                    }
                }
            }
        }
        
		OSTimeDlyHMSM(0, 0, 0, 5);
        
        TaskRunningCnt++;
        if(TaskRunningCnt > 20000){
          //printf("Key task running...\n");   
           TaskRunningCnt  = 0;
        }
//        Uart0_SendByte('K');
	}
}


void KeySend(uint8_t Key, uint8_t Pressed)
{ 
    
#ifdef USE_CRITICAL_WHEN_POST    
    
 #if OS_CRITICAL_METHOD == 3u	 
	 OS_CPU_SR cpu_sr  = 0u;
#endif	
	
	OS_ENTER_CRITICAL();
#endif	
    
    if(Pressed==KEY_DOWN){
        if(keyState==false){
            currentKey = Key;
            
            //背光键
            if(GUI_KEY_BKLINGHT == Key){
                GUI_LCDLightLoop();
                AudioPlayCnt(AUDIO_TYPE_KEY_NORMAL,AUDIO_PLAY_TIMES_KEY_NORMAL);
            }
            
            
            if(Key!=GUI_KEY_PTTDOWN&&Key!=GUI_KEY_BKLINGHT)
                GUI_StoreKeyMsg(Key,KEY_DOWN);
            
            keyState = true;
        }
    }
    else if(Pressed==KEY_UP){
        if(keyState==true&&currentKey==Key){
            currentKey = 0;
            if(Key!=GUI_KEY_PTTDOWN&&Key!=GUI_KEY_BKLINGHT)
                GUI_StoreKeyMsg(Key,KEY_UP);
            
            keyState = false;
            pressCnt = 3;
            timeCnt = 0;
        }
    }
#ifdef USE_CRITICAL_WHEN_POST 	
	OS_EXIT_CRITICAL();
#endif    
}

